﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using xn;
using System.Timers;

namespace KinectAPI.Gestures
{
    public class Volant : Gesture
    {
        private BodyTracker body;
        private BodyGestureGenerator bgg;

        private Dictionary<uint, object[]> users;

        public event EventHandler Start;

        public event EventHandler End;

        public event EventHandler Recognised;

        #region Constructor

        public Volant()
        {
        }

        public void construct(object[] args)
        {
            bgg = (BodyGestureGenerator)args[1];
            body = (BodyTracker)args[0];
            body.UsersUpdated += new BodyTracker.UsersUpdatedHandler(Users_Updated);

            users = new Dictionary<uint, object[]>();
        }

        #endregion

        public string getName()
        {
            return "Volant";
        }

        #region Event Handler

        void Users_Updated(object sender, UsersEventArgs e)
        {
            foreach (var user in e.users)
            {
                if (!users.ContainsKey(user.Id))
                {

                    users.Add(user.Id, new object[]{false, false, null, false, null});
                }

                int entree = 10;
                int sortie = 75;
                double handDistance = Math.Sqrt(Math.Pow((user.RightHand.X - user.LeftHand.X), 2) + Math.Pow((user.RightHand.Y - user.LeftHand.Y), 2));// *(user.RightHand.Z - user.LeftHand.Z);
                double elbowDistance = Math.Sqrt(Math.Pow((user.RightElbow.X - user.LeftElbow.X), 2) + Math.Pow((user.RightElbow.Y - user.LeftElbow.Y), 2));// *(user.RightElbow.Z - user.LeftElbow.Z);

                //si on cherche la pose de debut
                if (! (bool)users[user.Id][0])
                {
                    // si on detecte la pause
                    if (Math.Abs(handDistance - elbowDistance) < entree)
                    {
                        // si on attend pas le timer de l'entree de la pose
                        if (! (bool)users[user.Id][1])
                        {
                            users[user.Id][1] = true;
                            users[user.Id][2] = new System.Timers.Timer();
                            ((Timer)users[user.Id][2]).Elapsed += delegate { StartVolant(user.Id); };
                            ((Timer)users[user.Id][2]).Interval = 1000;
                            ((Timer)users[user.Id][2]).Enabled = true;
                        }
                    }
                    // si ce n'est pas la pose
                    else{
                        // si on attend le timer de l'entree de la pose
                        if ((bool)users[user.Id][1])
                        {
                            ((Timer)users[user.Id][2]).Stop();
                            users[user.Id][1] = false;
                        }
                    }
                }
                // si on est en mode Volant
                else
                {
                    // si on detecte la sortie de la pause
                    if (Math.Abs(handDistance - elbowDistance) > sortie)
                    {
                        // si on attend pas le timer de sortie de la pose
                        if (!(bool)users[user.Id][3])
                        {
                            users[user.Id][3] = true;
                            users[user.Id][4] = new System.Timers.Timer();
                            ((Timer)users[user.Id][4]).Elapsed += delegate { EndVolant(user.Id); };
                            ((Timer)users[user.Id][4]).Interval = 200;
                            ((Timer)users[user.Id][4]).Enabled = true;
                        }
                    }
                    else{
                        // si on attend le timer de sortie de la pose
                        if ((bool)users[user.Id][3])
                        {
                            ((Timer)users[user.Id][4]).Stop();
                            users[user.Id][3] = false;
                        }
                        // on calcul l'angle du volant
                        double angle = Math.Atan((user.RightHand.Y - user.LeftHand.Y) / (user.RightHand.X - user.LeftHand.X)) * 50;
                        Recognised(this, new GestureEventArgs(getName(), new object[]{angle}));
                    }
                }
            }
        }

        void StartVolant(uint Id)
        {
            ((Timer)users[Id][2]).Stop();
            users[Id][0] = true;
            Start(this, new GestureEventArgs(getName(), null));
        }

        void EndVolant(uint Id)
        {
            ((Timer)users[Id][4]).Stop();
            users[Id][0] = false;
            End(this, new GestureEventArgs(getName(), null));
        }

        #endregion
    }
}
